unit uControlCommand;

interface

uses
  Classes, windows, SysUtils;

procedure RunCommand(const ACmd, AWorkDir: string; AOutMsg: TStrings);



implementation

procedure RunCommand(const ACmd, AWorkDir: string; AOutMsg: TStrings);
const
  MAX_LEN = 1024;
var
  SA: TSecurityAttributes;
  SI: TStartupInfo;
  PI: TProcessInformation;
  StdOutPipeRead, StdOutPipeWrite: THandle;
  WasOK: Boolean;
  Buffer: array[0..MAX_LEN] of Char;
  LineBuf: array[0..MAX_LEN] of Char;
  i: integer;
  ic: integer;

  BytesRead: Cardinal;
  iOutMsgCount: integer;

  procedure AddMessage;
  var
    i: integer;
    bAvail: Boolean;
  begin
    if not Assigned(AOutMsg) then
      Exit;

    LineBuf[ic] := #0;
    bAvail := ic > 0;
    for i := 4 to ic - 1 do
      if LineBuf[i] = #32 then
      begin
        if (LineBuf[i - 2] in [#48..#57]) and (LineBuf[i - 1] = ')') then
          bAvail := (LineBuf[i + 1] <> #32) and (LineBuf[i + 1] <> #0);
        Break;
      end;

    if bAvail then
    begin
      if iOutMsgCount >= 2 then
        AOutMsg.Add(LineBuf);
      inc(iOutMsgCount);
    end;
    FillChar(LineBuf, Length(LineBuf), #0);
    ic := 0;
  end;

begin
  SA.nLength := SizeOf(TSecurityAttributes);
  SA.bInheritHandle := True;
  SA.lpSecurityDescriptor := nil;

  CreatePipe(StdOutPipeRead, StdOutPipeWrite, @SA, 0);
  try
    FillChar(SI, SizeOf(TStartupInfo), 0);
    SI.cb := SizeOf(SI);
    SI.dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;
    SI.wShowWindow := SW_HIDE;
    SI.hStdInput := GetStdHandle(STD_INPUT_HANDLE);
    SI.hStdOutput := StdOutPipeWrite;
    SI.hStdError := StdOutPipeWrite;

    CreateProcess(nil, pchar(ACmd), nil, nil, True, 0, nil,
      PChar(AWorkDir), SI, PI);
    try
      CloseHandle(StdOutPipeWrite);
      LineBuf[0] := #0;
      iOutMsgCount := 0;
      ic := 0;
      repeat
        WasOK := ReadFile(StdOutPipeRead, Buffer, MAX_LEN, BytesRead, nil);


        if BytesRead > 0 then
        begin
          for i := 0 to BytesRead - 1 do
          begin
            if ic = MAX_LEN then
              AddMessage;

            case Buffer[i] of
              #13: AddMessage;
              #10: Continue;
            else
              begin
                LineBuf[ic] := Buffer[i];
                inc(ic);
              end;

            end;
          end;
        end;
      until not WasOK or (BytesRead = 0);

      if (ic > 0) and Assigned(AOutMsg) then
        AOutMsg.Add(LineBuf);

      WaitForSingleObject(PI.hProcess, INFINITE);
    finally
      CloseHandle(PI.hThread);
      CloseHandle(PI.hProcess);
    end;

  finally
    CloseHandle(StdOutPipeRead);
  end;
end;



function CreateWinProc(const ACmd: string; Visibility: Integer):
    TProcessInformation;
var
  rAppName: array[0..512] of Char;
  rCurdir: array[0..256] of Char;
  sWorkDir: string;
  rSI: TStartupInfo;
  rPI: TProcessInformation;
begin
  //AppExists := FileExists(ACmd);
  StrPCopy(rAppName, ACmd);
  GetDir(0, sWorkDir);
  StrPCopy(rCurdir, sWorkDir);
  FillChar(rSI, Sizeof(rSI), #0);

  rSI.cb := Sizeof(rSI);
  rSI.dwFlags := STARTF_USESHOWWINDOW;
  rSI.wShowWindow := Visibility;
  CreateProcess(
    nil,
    rAppName,
    nil,
    nil,
    False,
    CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS,
    nil,
    nil,
    rSI,
    rPI);
  Result := rPI;
end;

end.

